﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Project.IRepository;
using Project.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Project.Service
{
    public class BaseService<T> where T : BaseModel, new()
    {
        public IBaseRepository baseRepostory;
        public IUnitOfWork unitOfWork;
        public readonly IMapper mapper;

        public BaseService(IBaseRepository repostory, IUnitOfWork unitOfWork, IMapper mapper)
        {
            this.baseRepostory = repostory;
            this.unitOfWork = unitOfWork;
            this.mapper = mapper;
        }


        public virtual async Task<int> AddAsync(T obj)
        {
            baseRepostory.Add<T>(obj);
            return await unitOfWork.SaveChangesAsync();
        }

        public virtual async Task<int> AddAsync<DTO>(DTO dto)
        {
            T entity = mapper.Map<T>(dto);
            entity.CreateAt = DateTime.Now;
            baseRepostory.Add<T>(entity);
            return await unitOfWork.SaveChangesAsync();
        }

        public virtual async Task<int> DeleteAsync(Guid id)
        {
            baseRepostory.Delete<T>(id);
            return await unitOfWork.SaveChangesAsync();
        }

        public async Task<int> MarkDeleteAsync(Guid id)
        {
            var entity = new T() { Id = id, IsDeleted = true };
            baseRepostory.Update<T>(entity, "IsDeleted");
            return await unitOfWork.SaveChangesAsync();
        }

        public virtual async Task<int> EditAsync(T obj)
        {
            baseRepostory.Update<T>(obj);
            return await unitOfWork.SaveChangesAsync();
        }

        public async Task<int> EditAsync(T obj, params string[] fields)
        {
            baseRepostory.Update(obj, fields);
            return await unitOfWork.SaveChangesAsync();
        }

        public virtual async Task<T> GetEntityAsync(Expression<Func<T, bool>> expression)
        {
            return await baseRepostory.Find(expression).FirstOrDefaultAsync();
        }

        public virtual async Task<T> GetEntityAsync(Guid id)
        {
            return await baseRepostory.FindAsync<T>(id);
        }


        public IQueryable<T> GetList(Expression<Func<T, bool>> expression = null)
        {
            if (expression == null)
                expression = t => true;
            return baseRepostory.Find(expression);
        }

        public IQueryable<T> GetList<TOrder>(Expression<Func<T, bool>> expression, int pageSize, int pageIndex, out int total, Expression<Func<T, TOrder>> order = null, bool IsAsc = true)
        {
            if (order == null)
                return baseRepostory.Find<T, DateTime?>(pageIndex, pageSize, expression, d => d.CreateAt, out total, IsAsc);
            return baseRepostory.Find<T, TOrder>(pageIndex, pageSize, expression, order, out total, IsAsc);
        }

        public async Task<bool> ExistsAsync(Expression<Func<T,bool>> expression)
        {
            return await baseRepostory.ExistsAsync<T>(expression);
        }
    }
}
